﻿//////////////////////////////////////////////////
//                 WhiteMage.cs                 //
//         Part of RebornCo by kaihaider        //
//////////////////////////////////////////////////

using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Media;
using Buddy.Coroutines;
using ff14bot;
using ff14bot.Enums;
using ff14bot.Helpers;
using ff14bot.Managers;
using ff14bot.Objects;
using RebornCo.Helpers;
using RebornCo.Settings;
using TreeSharp;

namespace RebornCo.Rotations
{
    public class WhiteMage : RebornCoRoutine
    {
        public override void OnInitialize()
        {
            WantHealing = true;
            WindowSettings = new WhiteMageSetting();
        }

        public static WhiteMageSetting WhiteMageSettings
        {
            get { return WindowSettings as WhiteMageSetting; }
        }
        public sealed override ClassJobType[] Class
        {
            get
            {
                return new [] 
                { 
                 ClassJobType.WhiteMage, ClassJobType.Conjurer
                };
            }
        }
        #region Shared
        [Behavior(BehaviorType.PreCombatBuffs)]
        public Composite WhiteMageCreateBasicPreCombatBuffs()
        {
            return new ActionRunCoroutine(ctx => WhiteMageBuildPreCombatBuffs());
        }
        public static async Task<bool> WhiteMageBuildPreCombatBuffs()
        {
            if (!IsValid()) return false;
            if (Resting)
            {
                if (!Core.Player.IsCasting && await Spell.Cast("Cure", Core.Player, WhiteMageSettings.CureI && Core.Player.CurrentHealthPercent < 70 && Core.Player.CurrentHealthPercent < Core.Player.CurrentManaPercent)) return true;
                if (!Core.Player.IsCasting && await Spell.Cast("Physick", Core.Player, Core.Player.CurrentHealthPercent < 70 && Core.Player.CurrentHealthPercent < Core.Player.CurrentManaPercent)) return true;
                return false;
            }
            if (WhiteMageSettings.Protect && await Spell.BuffParty("Protect")) return true;
            if (WhiteMageSettings.Stoneskin && await Spell.BuffParty("Stoneskin")) return true;
            return await CombatCompanion();
        }
        [Behavior(BehaviorType.Rest)]
        public Composite WhiteMageCreateBasicRest()
        {
            return new ActionRunCoroutine(ctx => DefaultRestBehavior(Core.Player.CurrentManaPercent)); 
        }
        [Behavior(BehaviorType.CombatBuffs)]
        public Composite WhiteMageCreateBasicCombatBuffs()
        {
            return new ActionRunCoroutine(ctx => WhiteMageBuildCombatBuffs()); 
        }
        public static async Task<bool> WhiteMageBuildCombatBuffs()
        {
            ShouldPulse = true;
            if (Spell.GcdTime < WhiteMageSettings.NoneGcdWindowEnd) return false;
            if (WhiteMageSettings.CooldownsUsable && !Spell.UsedNoneGcd && await Spell.Cast("Invigorate", Core.Player, Core.Player.CurrentTPPercent < 50))
            {
                Spell.UsedNoneGcd = true;
                return true;
            }
            if (WhiteMageSettings.CooldownsUsable && !Spell.UsedNoneGcd && await Spell.Cast("Blood For Blood", Core.Player, true))
            {
                Spell.UsedNoneGcd = true;
                return true;
            }
            if (!Spell.UsedNoneGcd && await Spell.CastLock("Internal Release", Core.Player, true))
            {
                Spell.UsedNoneGcd = true;
                return true;
            }
            if (WindowSettings.CooldownsUsable && Spell.Potion != null && Spell.Potion.IsValid
                && Spell.Potion.CanUse(Core.Player) && Spell.Potion.Name.Equals(WindowSettings.PotionName))
            {
                Spell.Potion.UseItem(Core.Player);
                if (WindowSettings.PotionForce) Spell.UsedNoneGcd = true;
            }
            if (WhiteMageSettings.CooldownsUsable && !Spell.UsedNoneGcd && await Spell.CastLock("Foresight", Core.Player))
            {
                Spell.UsedNoneGcd = true;
                return true;
            }
            if (WhiteMageSettings.CooldownsUsable && !Spell.UsedNoneGcd && await Spell.Cast("Bloodbath", Core.Player, true))
            {
                Spell.UsedNoneGcd = true;
                return true;
            }
            if (WhiteMageSettings.CooldownsUsable && !Spell.UsedNoneGcd && await Spell.Cast("Raging Strikes", Core.Player, true))
            {
                Spell.UsedNoneGcd = true;
                return true;
            }
            if (WhiteMageSettings.CooldownsUsable && !Spell.UsedNoneGcd && await Spell.Cast("Keen Flurry", Core.Player, Core.Player.CurrentHealthPercent < 80))
            {
                Spell.UsedNoneGcd = true;
                return true;
            }
            if (WhiteMageSettings.CooldownsUsable && !Spell.UsedNoneGcd && await Spell.Cast("Foresight", Core.Player, Core.Player.CurrentHealthPercent < 60))
            {
                Spell.UsedNoneGcd = true;
                return true;
            }
            if (WhiteMageSettings.CooldownsUsable && !Spell.UsedNoneGcd && await Spell.Cast("Convalescence", Core.Player, Core.Player.CurrentHealthPercent < 70))
            {
                Spell.UsedNoneGcd = true;
                return true;
            }
            if (WhiteMageSettings.CooldownsUsable && !Spell.UsedNoneGcd && await Spell.Cast("Second Wind", Core.Player, Core.Player.CurrentHealthPercent < 40))
            {
                Spell.UsedNoneGcd = true;
                return true;
            }
            if (WhiteMageSettings.CooldownsUsable && !Spell.UsedNoneGcd && await Spell.Cast("Awareness", Core.Player, Core.Player.CurrentHealthPercent < 30))
            {
                Spell.UsedNoneGcd = true;
                return true;
            }
            if (WhiteMageSettings.CooldownsUsable && !Spell.UsedNoneGcd && await Spell.Cast("Featherfoot", Core.Player, Core.Player.Distance2D() < 5))
            {
                Spell.UsedNoneGcd = true;
                return true;
            }
            return false;
        }
        #endregion
        #region World
        [Behavior(BehaviorType.Pull, ClassJobType.Adventurer, GameContext.Normal)]
        public Composite WhiteMageCreateBasicPull()
        {
            return new ActionRunCoroutine(ctx => WhiteMageBuildPullBehavior()); 
        }
        public static async Task<bool> WhiteMageBuildPullBehavior()
        {
            if (Core.Player.CurrentTarget != null && !Core.Player.CurrentTarget.CanAttack || !IsValid()) return false;
            await Target.EnsureValidTarget();
            if (await Movement.PullMove(Core.Player.CurrentTarget)) return true;
            ShouldPulse = true;
            if (!Spell.Gcd && await Spell.PullCast("Stone", Core.Player.CurrentTarget, true)
                &&(Core.Player.CurrentTarget as BattleCharacter) != null && (Core.Player.CurrentTarget as BattleCharacter).IsAlive)
            {//change to wait til not casting then wait gcd
                await Coroutine.Sleep(250);
                await Coroutine.Wait(2500, Spell.NotCasting);
                await Coroutine.Wait(2500, Spell.InvalidOrOutGcdCon);
                return await Spell.PullCast("Stone II", Core.Player.CurrentTarget, true);
            }
            return false;
        }

        [Behavior(BehaviorType.Combat, ClassJobType.Adventurer, GameContext.Normal)]
        public Composite WhiteMageCreateBasicCombat()
        {
            return new ActionRunCoroutine(ctx => WhiteMageBuildBasicCombat()); 
        }
        public static async Task<bool> WhiteMageBuildBasicCombat()
        {
            await Target.EnsureValidTarget();
            await Movement.MoveToTarget();
            ShouldPulse = true;
            if (Core.Player.CurrentTarget != null && MovementManager.IsMoving
                && !(Core.Player.CurrentTarget.InLineOfSight() && Movement.IsInSafeRange(Core.Player.CurrentTarget))) return true;
            if (!Spell.Gcd && await Spell.Cast("Cure", Core.Player, WhiteMageSettings.CureI && HealTargeting.Instance.FirstUnit == null && Core.Player.CurrentHealthPercent < 45)) return true;
            if (!Spell.Gcd && WhiteMageSettings.AutoClericStance && await Spell.Cast("Cleric Stance", Core.Player,
                Core.Player.CurrentTarget != null && Core.Player.CurrentTarget.CanAttack 
                && HealTargeting.Instance.FirstUnit != null && HealTargeting.Instance.FirstUnit.CurrentHealthPercent > 75 
                && !Core.Player.HasAura("Cleric Stance"), false, true, true)) return true;
            if (WhiteMageSettings.CooldownsUsable && await Spell.CastLock("Shroud of Saints", Core.Player, Core.Player.MaxMana - Core.Player.CurrentMana > 1200)) return true;
            if (!Spell.Gcd && await Spell.CastLock("Aero II", Core.Player.CurrentTarget, !Core.Player.CurrentTarget.HasAura("Aero II",true,WhiteMageSettings.AeroClip))) return true;
            if (!Spell.Gcd && await Spell.CastLock("Aero", Core.Player.CurrentTarget, Core.Player.ClassLevel < 46 && !Core.Player.CurrentTarget.HasAura("Aero", true, WhiteMageSettings.AeroClip))) return true;
            if (await Spell.CastLock("Thunder", Core.Player.CurrentTarget, !Core.Player.CurrentTarget.HasAura("Thunder"))) return true;
            if (!Spell.Gcd && await Spell.CastLock("Fluid Aura", Core.Player.CurrentTarget, Core.Player.Distance2D() <= 15f)) return true;
            if (!Spell.Gcd && await Spell.Cast("Stone II", Core.Player.CurrentTarget, true)) return true;
            if (!Spell.Gcd && await Spell.Cast("Stone", Core.Player.CurrentTarget, true)) return true;

            return false;
        }
        [Behavior(BehaviorType.Heal, ClassJobType.Adventurer, GameContext.Normal)]
        public Composite WhiteMageCreateBasicHeal()
        {
            return new ActionRunCoroutine(ctx => WhiteMageBuildBasicHeal()); 

        }
        public static async Task<bool> WhiteMageBuildBasicHeal()
        {
            if (!IsValid()) return false;
            ShouldPulse = true;
            if (HealTargeting.Instance.FirstUnit == null) return false;
            await RaiseScan();
            if (WhiteMageSettings.Raise && (HealTargeting.Instance.FirstUnit == null || HealTargeting.Instance.FirstUnit.CurrentHealthPercent > WhiteMageSettings.HealthPercent)
                && (!WhiteMageSettings.RaiseBrezOnlyWithSwift || !Core.Player.InCombat) && RaiseTarget != 0
    && await Spell.Cast("Raise", GameObjectManager.GetObjectByObjectId(RaiseTarget)))
                return true;
            if (WhiteMageSettings.Movement && HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.HealthPercent &&
                (HealTargeting.Instance.FirstUnit.Distance2D() > 29 || !HealTargeting.Instance.FirstUnit.InLineOfSight())
                &&
                !(Core.Player.IsCasting &&
                  GameObjectManager.GetObjectByObjectId(Core.Player.SpellCastInfo.TargetId).InLineOfSight() &&
                  (Core.Player.SpellCastInfo.SpellData == null
                   ||
                   GameObjectManager.GetObjectByObjectId(Core.Player.SpellCastInfo.TargetId).Distance2D() <
                   Core.Player.SpellCastInfo.SpellData.Range)))
            {
                MovingForHeal = true;
                Movement.MoveTo(HealTargeting.Instance.FirstUnit);
            }
            if (MovingForHeal && MovementManager.IsMoving && HealTargeting.Instance.FirstUnit.Distance2D() < 29 &&
                HealTargeting.Instance.FirstUnit.InLineOfSight())
            {
                MovingForHeal = false;
                Movement.StopMove();
            }
            if (WhiteMageSettings.CooldownsUsable && await Spell.CastLock("Shroud of Saints", Core.Player, Core.Player.MaxMana - Core.Player.CurrentMana > 1200)) return true;
            //Logging.Write(Colors.Teal, "[RebornCo] " + HealTargeting.Instance.FirstUnit.Name + ": " + HealTargeting.Instance.FirstUnit.CurrentHealthPercent);
            if (WhiteMageSettings.ScanForOverheal && Core.Player.IsCasting)
            {
                if (Core.Player.CastingSpellId == 120 || Core.Player.CastingSpellId == 135)
                {
                    if (HealTargeting.Instance.FirstUnit.CurrentHealthPercent > 95)
                    {
                        Logging.Write(Colors.Orchid, "[RebornCo] Everyone Topped Off? Killing Cast");
                        Actionmanager.StopCasting();
                    }
                    else
                    {
                        var target = GameObjectManager.GetObjectByObjectId(Core.Player.SpellCastInfo.TargetId);
                        if (target != null && target.IsValid && target.CurrentHealthPercent > 95)
                        {
                            Logging.Write(Colors.Orchid, "[RebornCo] Heal Target was topped off! Killing Cast");
                            Actionmanager.StopCasting();
                        }
                    }
                }
                if (WhiteMageSettings.MedicaOverHealPrevention && Core.Player.CastingSpellId == 124 && HealTargeting.D15 <= WhiteMageSettings.MedicaOverhealCount)
                {
                    Logging.Write(Colors.Orchid, "[RebornCo] " + HealTargeting.D15 + " Targets need healing. " + (WhiteMageSettings.MedicaOverhealCount + 1) + " are required to continue cast. Killing Cast");
                    Actionmanager.StopCasting();
                }
                if (WhiteMageSettings.MedicaOverHealPrevention && Core.Player.CastingSpellId == 133 && HealTargeting.D25 <= WhiteMageSettings.MedicaOverhealCount)
                {
                    Logging.Write(Colors.Orchid, "[RebornCo] " + HealTargeting.D25 + " Targets need healing. " + (WhiteMageSettings.MedicaOverhealCount + 1) + " are required to continue cast. Killing Cast");
                    Actionmanager.StopCasting();
                }
            }
            if (WhiteMageSettings.Raise && RaiseTarget != 0 && Core.Player.InCombat
                && Actionmanager.CurrentActions.ContainsKey("Swiftcast")
                && !(WhiteMageSettings.RaiseDontSwiftBrezDuringPoM && Core.Player.HasAura("Presence of Mind")))
            {
                if (RaiseSwift < DateTime.UtcNow.TimeOfDay)
                {
                    if (!Extensions.DoubleCastPreventionDict.Contains(null, "Swiftcast"))
                    {
                        RaiseSwift = DateTime.UtcNow.TimeOfDay + TimeSpan.FromSeconds(5);
                        await Spell.Cast("Swiftcast", Core.Player, true, true);
                    }
                    else if (RaiseSwiftFlush)
                    {
                        Extensions.UpdateDoubleCastDictSpecific("Raise", GameObjectManager.GetObjectByObjectId(RaiseTarget), WhiteMageSettings.RaiseSecondsofDoubleCastProtection);
                        RaiseSwiftFlush = false;
                        RaiseTarget = 0;
                    }
                }
                else
                {
                    RaiseSwiftFlush = true;
                    await Spell.Cast("Swiftcast", Core.Player, true, true);
                    if (Extensions.DoubleCastPreventionDict.Contains(null, "Swiftcast"))
                        await Spell.ConfirmedCast("Raise", GameObjectManager.GetObjectByObjectId(RaiseTarget), true, false, true);
                    return true;
                }
            }
            await EsunaScan();
            if (!Spell.Gcd && WhiteMageSettings.Esuna && WhiteMageSettings.EsunaBeforeHeals && EsunaTarget != 0
                && await Spell.CastLock("Esuna", GameObjectManager.GetObjectByObjectId(EsunaTarget), HealTargeting.Instance.FirstUnit.CurrentHealthPercent > WhiteMageSettings.EsunaIfNoOneBelowHp))
                return true;
            if (!Spell.Gcd && WhiteMageSettings.CureII && await Spell.CastLock("Cure II", HealTargeting.Instance.FirstUnit, HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.HealthPercent
                && (!Core.Player.IsCasting || !(Core.Player.CastingSpellId == 120 || Core.Player.CastingSpellId == 135))
                && Core.Player.HasAura("Freecure"))) return true; 
            if (!Spell.Gcd && WhiteMageSettings.AutoClericStance && await Spell.Cast("Cleric Stance", Core.Player, HealTargeting.Instance.FirstUnit.CurrentHealthPercent < 75 && Core.Player.HasAura("Cleric Stance"), false, true, true)) return true;
            if (WhiteMageSettings.CooldownsUsable && WhiteMageSettings.PresenceofMind && (!PartyManager.IsInParty && Core.Player.CurrentHealthPercent < WhiteMageSettings.CriticalHealthPercent || HealTargeting.PeopleDying >= WhiteMageSettings.CriticalHealthCount)
                && await Spell.CastLock("Presence of Mind", Core.Player, true)) return true;
            if (WhiteMageSettings.CooldownsUsable && WhiteMageSettings.DivineSeal && (!PartyManager.IsInParty && Core.Player.CurrentHealthPercent < WhiteMageSettings.CriticalHealthPercent || HealTargeting.PeopleDying >= WhiteMageSettings.CriticalHealthCount)
                && await Spell.CastLock("Divine Seal", Core.Player, true)) return true;
            if (WhiteMageSettings.CooldownsUsable && await Spell.CastLock("Benediction", HealTargeting.Instance.FirstUnit, HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.Benediction
                && (!WhiteMageSettings.OnlyBenedictionTank || WhiteMageSettings.TankName != null && HealTargeting.Instance.FirstUnit.Name.ToLower().Contains(WhiteMageSettings.TankName.ToLower())))) return true;
            if (!Spell.Gcd && WhiteMageSettings.Medica1 && await Spell.CastLock("Medica", HealTargeting.Instance.FirstUnit, HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.HealthPercent
                && HealTargeting.D15 >= WhiteMageSettings.MedicaCount)) return true;
            if (!Spell.Gcd && WhiteMageSettings.Medica2 && await Spell.CastLock("Medica II", HealTargeting.Instance.FirstUnit, HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.HealthPercent
                && HealTargeting.D25 >= WhiteMageSettings.MedicaCount)) return true;
            if (!Spell.Gcd && await Spell.CastLock("Regen", HealTargeting.Instance.FirstUnit, HealTargeting.Instance.FirstUnit.CurrentHealthPercent > WhiteMageSettings.RegenMinHpPercent
                && (!WhiteMageSettings.RegenMaxHpPercentUse && HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.HealthPercent
                || WhiteMageSettings.RegenMaxHpPercentUse && HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.RegenMaxHpPercent)
                && !HealTargeting.Instance.FirstUnit.HasAura("Regen", true, WhiteMageSettings.RegenClip))) return true;
            if (!Spell.Gcd && WhiteMageSettings.CureI && await Spell.Cast("Cure", HealTargeting.Instance.FirstUnit, HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.RegenCureHpPercent
                || HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.HealthPercent && (HealTargeting.Instance.FirstUnit.ObjectId == WhiteMageSettings.TankId
                    || !HealTargeting.Instance.FirstUnit.HasAura("Regen", true, WhiteMageSettings.RegenClip)))) 
                return true;
            if (!Spell.Gcd && WhiteMageSettings.Esuna && !WhiteMageSettings.EsunaBeforeHeals && EsunaTarget != 0
                && await Spell.CastLock("Esuna", GameObjectManager.GetObjectByObjectId(EsunaTarget)))
                return true;
            return false;
        }

        #endregion
        #region Instance
        [Behavior(BehaviorType.Pull, ClassJobType.Adventurer, GameContext.Instances)]
        public Composite WhiteMageCreateInstancePull()
        {
            return new ActionRunCoroutine(ctx => WhiteMageBuildInstancePullBehavior());
        }
#pragma warning disable 1998
        public static async Task<bool> WhiteMageBuildInstancePullBehavior()
#pragma warning restore 1998
        {
            //await Target.EnsureValidTarget();
            return false;
        }

        [Behavior(BehaviorType.Combat, ClassJobType.Adventurer, GameContext.Instances)]
        public Composite WhiteMageCreateInstanceCombat()
        {
            return new ActionRunCoroutine(ctx => WhiteMageBuildInstanceCombat());
        }
#pragma warning disable 1998
        public static async Task<bool> WhiteMageBuildInstanceCombat()
#pragma warning restore 1998
        {
            //await Target.EnsureValidTarget();
            //await Movement.MoveToTarget();
            return false;
        }

        [Behavior(BehaviorType.Heal, ClassJobType.Adventurer, GameContext.Instances)]
        public Composite WhiteMageCreateInstanceHeal()
        {
            return new ActionRunCoroutine(ctx => WhiteMageBuildInstanceHeal());

        }
        public static async Task<bool> WhiteMageBuildInstanceHeal()
        {
            if (!IsValid()) return false;
            ShouldPulse = true;
            if (WhiteMageSettings.AutoClericStance && await Spell.CastLock("Cleric Stance", Core.Player, Core.Player.HasAura("Cleric Stance"))) return true;
            if (HealTargeting.Instance.FirstUnit == null) return false;
            await RaiseScan();
            if (WhiteMageSettings.Raise && (HealTargeting.Instance.FirstUnit == null || HealTargeting.Instance.FirstUnit.CurrentHealthPercent > WhiteMageSettings.HealthPercent)
                && (!WhiteMageSettings.RaiseBrezOnlyWithSwift || !Core.Player.InCombat) && RaiseTarget != 0
                && await Spell.Cast("Raise", GameObjectManager.GetObjectByObjectId(RaiseTarget)))
                return true;
            if (WhiteMageSettings.Movement && HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.HealthPercent && (HealTargeting.Instance.FirstUnit.Distance2D() > 29 || !HealTargeting.Instance.FirstUnit.InLineOfSight())
                && !(Core.Player.IsCasting && GameObjectManager.GetObjectByObjectId(Core.Player.SpellCastInfo.TargetId).InLineOfSight() && (Core.Player.SpellCastInfo.SpellData == null
                || GameObjectManager.GetObjectByObjectId(Core.Player.SpellCastInfo.TargetId).Distance2D() < Core.Player.SpellCastInfo.SpellData.Range)) )
            {
                MovingForHeal = true;
                Movement.MoveTo(HealTargeting.Instance.FirstUnit);
            }
            if (MovingForHeal && MovementManager.IsMoving && HealTargeting.Instance.FirstUnit.Distance2D() < 29 &&
                HealTargeting.Instance.FirstUnit.InLineOfSight())
            {
                MovingForHeal = false;
                Movement.StopMove();
            }
            if (WhiteMageSettings.CooldownsUsable && await Spell.CastLock("Shroud of Saints", Core.Player, Core.Player.MaxMana - Core.Player.CurrentMana > 1200)) return true;
            //Logging.Write(Colors.Teal, "[RebornCo] " + HealTargeting.Instance.FirstUnit.Name + ": " + HealTargeting.Instance.FirstUnit.CurrentHealthPercent);
            if (WhiteMageSettings.ScanForOverheal && Core.Player.IsCasting)
            {
                if(Core.Player.CastingSpellId == 120 || Core.Player.CastingSpellId == 135)
                {
                    if (HealTargeting.Instance.FirstUnit.CurrentHealthPercent > 95)
                    {
                        Logging.Write(Colors.Orchid, "[RebornCo] Everyone Topped Off? Killing Cast");
                        Actionmanager.StopCasting();
                    }
                    else
                    {
                        var target = GameObjectManager.GetObjectByObjectId(Core.Player.SpellCastInfo.TargetId);
                        if (target != null && target.IsValid && target.CurrentHealthPercent > 95)
                        {
                            Logging.Write(Colors.Orchid, "[RebornCo] Heal Target was topped off! Killing Cast");
                            Actionmanager.StopCasting();
                        }
                    }
                }
                if (WhiteMageSettings.MedicaOverHealPrevention && Core.Player.CastingSpellId == 124 && HealTargeting.D15 <= WhiteMageSettings.MedicaOverhealCount)
                {
                    Logging.Write(Colors.Orchid, "[RebornCo] " + HealTargeting.D15 + " Targets need healing. "+ (WhiteMageSettings.MedicaOverhealCount + 1) + " are required to continue cast. Killing Cast");
                    Actionmanager.StopCasting();
                }
                if (WhiteMageSettings.MedicaOverHealPrevention && Core.Player.CastingSpellId == 133 && HealTargeting.D25 <= WhiteMageSettings.MedicaOverhealCount)
                {
                    Logging.Write(Colors.Orchid, "[RebornCo] " + HealTargeting.D25 + " Targets need healing. " + (WhiteMageSettings.MedicaOverhealCount + 1) + " are required to continue cast. Killing Cast");
                    Actionmanager.StopCasting();
                }
            }
            if (WhiteMageSettings.Raise && RaiseTarget != 0 && Core.Player.InCombat
                && Actionmanager.CurrentActions.ContainsKey("Swiftcast")
                && !(WhiteMageSettings.RaiseDontSwiftBrezDuringPoM && Core.Player.HasAura("Presence of Mind")))
            {
                if (RaiseSwift < DateTime.UtcNow.TimeOfDay)
                {
                    if (!Extensions.DoubleCastPreventionDict.Contains(null, "Swiftcast"))
                    {
                        RaiseSwift = DateTime.UtcNow.TimeOfDay + TimeSpan.FromSeconds(5);
                        await Spell.Cast("Swiftcast", Core.Player, true, true);
                    }
                    else if (RaiseSwiftFlush)
                    {
                        Extensions.UpdateDoubleCastDictSpecific("Raise", GameObjectManager.GetObjectByObjectId(RaiseTarget), WhiteMageSettings.RaiseSecondsofDoubleCastProtection);
                        RaiseSwiftFlush = false;
                        RaiseTarget = 0;
                    }
                }
                else
                {
                    RaiseSwiftFlush = true;
                    await Spell.Cast("Swiftcast", Core.Player, true, true);
                    if (Extensions.DoubleCastPreventionDict.Contains(null, "Swiftcast"))
                        await Spell.ConfirmedCast("Raise", GameObjectManager.GetObjectByObjectId(RaiseTarget), true, false, true);
                    return true;
                }
            }
            await EsunaScan();
            if (!Spell.Gcd && WhiteMageSettings.Esuna && WhiteMageSettings.EsunaBeforeHeals && EsunaTarget != 0
                && await Spell.CastLock("Esuna", GameObjectManager.GetObjectByObjectId(EsunaTarget), HealTargeting.Instance.FirstUnit.CurrentHealthPercent > WhiteMageSettings.EsunaIfNoOneBelowHp))
                return true;
            if (!Spell.Gcd && WhiteMageSettings.CureII && await Spell.CastLock("Cure II", HealTargeting.Instance.FirstUnit, HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.HealthPercent
                && (!Core.Player.IsCasting || !(Core.Player.CastingSpellId == 120 || Core.Player.CastingSpellId == 135))
                && Core.Player.HasAura("Freecure"))) return true;
            if (WhiteMageSettings.CooldownsUsable && WhiteMageSettings.PresenceofMind && HealTargeting.PeopleDying >= WhiteMageSettings.CriticalHealthCount
                && await Spell.CastLock("Presence of Mind", Core.Player, true)) return true;
            if (WhiteMageSettings.CooldownsUsable && WhiteMageSettings.DivineSeal && HealTargeting.PeopleDying >= WhiteMageSettings.CriticalHealthCount
                && await Spell.CastLock("Divine Seal", Core.Player, true)) return true;
            if (WhiteMageSettings.CooldownsUsable && await Spell.CastLock("Benediction", HealTargeting.Instance.FirstUnit, HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.Benediction
                && (!WhiteMageSettings.OnlyBenedictionTank || WhiteMageSettings.TankName != null && HealTargeting.Instance.FirstUnit.Name.ToLower().Contains(WhiteMageSettings.TankName.ToLower())))) return true;
            if (!Spell.Gcd && WhiteMageSettings.Medica1 && await Spell.CastLock("Medica", HealTargeting.Instance.FirstUnit, HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.HealthPercent 
                && HealTargeting.D15>=WhiteMageSettings.MedicaCount)) return true;
            if (!Spell.Gcd && WhiteMageSettings.Medica2 && await Spell.CastLock("Medica II", HealTargeting.Instance.FirstUnit, HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.HealthPercent
                && HealTargeting.D25 >= WhiteMageSettings.MedicaCount)) return true;
            if (!Spell.Gcd && await Spell.CastLock("Regen", HealTargeting.Instance.FirstUnit, HealTargeting.Instance.FirstUnit.CurrentHealthPercent > WhiteMageSettings.RegenMinHpPercent
                && (!WhiteMageSettings.RegenMaxHpPercentUse && HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.HealthPercent
                || WhiteMageSettings.RegenMaxHpPercentUse && HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.RegenMaxHpPercent)
                && !HealTargeting.Instance.FirstUnit.HasAura("Regen", true, WhiteMageSettings.RegenClip))) return true;
            if (!Spell.Gcd && WhiteMageSettings.CureI && await Spell.Cast("Cure", HealTargeting.Instance.FirstUnit, HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.RegenCureHpPercent
                || HealTargeting.Instance.FirstUnit.CurrentHealthPercent < WhiteMageSettings.HealthPercent && (HealTargeting.Instance.FirstUnit.ObjectId == WhiteMageSettings.TankId
                    || !HealTargeting.Instance.FirstUnit.HasAura("Regen", true, WhiteMageSettings.RegenClip))
                )) return true;
            if (!Spell.Gcd && WhiteMageSettings.Esuna && !WhiteMageSettings.EsunaBeforeHeals && EsunaTarget != 0
                && await Spell.CastLock("Esuna", GameObjectManager.GetObjectByObjectId(EsunaTarget)))
                return true;
            return false;
        }
        #endregion

        public static bool RaiseSwiftFlush;
        public static TimeSpan RaiseSwift;
        public static uint RaiseTarget;
#pragma warning disable 1998
        public static async Task RaiseScan()
#pragma warning restore 1998
        {//worth extra checks to raise tank first?
            if (Core.Player.IsCasting && Core.Player.CastingSpellId == 125 && !Extensions.DoubleCastPreventionDict.Contains(GameObjectManager.GetObjectByObjectId(Core.Player.SpellCastInfo.TargetId), "Raise"))
            {
                Extensions.UpdateDoubleCastDictSpecific("Raise", GameObjectManager.GetObjectByObjectId(Core.Player.SpellCastInfo.TargetId),WhiteMageSettings.RaiseSecondsofDoubleCastProtection);
                RaiseTarget = 0;

                if (WindowSettings.Debug)
                    Logging.WriteToFileSync(LogLevel.Normal, "(RebornCo) RaiseTarget Cleared");
                return;
            }
            if (RaiseTarget != 0)
            {
                var rt = GameObjectManager.GetObjectByObjectId(RaiseTarget);
                if ((rt as Character) != null && (rt as Character).IsValid && (rt as Character).IsDead) return;
            }
            var target = PartyManager.VisibleMembers.FirstOrDefault(
                unit => unit.IsValid && (unit.GameObject as Character) != null
                    && (unit.GameObject as Character).IsDead && unit.GameObject.Type == GameObjectType.Pc
                    && !Extensions.DoubleCastPreventionDict.Contains(unit.GameObject, "Raise")
                    && unit.GameObject.Distance2D() < 30);

            if (WindowSettings.Debug && target != null)
                Logging.WriteToFileSync(LogLevel.Normal, "(RebornCo) RaiseTarget set: " + target.ObjectId);

            RaiseTarget = target == null ? 0 : target.ObjectId;
        }

        public static bool MovingForHeal;
        public static uint EsunaTarget;
#pragma warning disable 1998
        public static async Task EsunaScan()
#pragma warning restore 1998
        {
            var target = PartyManager.VisibleMembers.FirstOrDefault(
                unit => unit.IsValid && unit.GameObject.Distance2D() < 30
                    && unit.GameObject.HasAura(WhiteMageSettings.EsunaList, false, WhiteMageSettings.EsunaClip));

            EsunaTarget = target == null ? 0 : target.ObjectId;
        }
    }
}
